/* -*-mode:java; c-basic-offset:2; -*- */
/* JCTerm
 * Copyright (C) 2002,2007 ymnk, JCraft,Inc.
 *  
 * Written by: ymnk<ymnk@jcaft.com>
 *   
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
   
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package sputty.terminal;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.awt.image.*;
import java.util.ArrayList;
import sputty.classes.SendCommands;

public class SwingTerminal extends JPanel implements KeyListener, Runnable, Term, ClipboardOwner{
    OutputStream out;
    InputStream in;
    Emulator emulator=null;

    Connection connection=null;

    private BufferedImage img;
    private BufferedImage background;
    private Graphics2D cursor_graphics;
    private Graphics2D graphics;
    private java.awt.Color defaultbground=Color.black;
    private java.awt.Color defaultfground=Color.white;
    private java.awt.Color bground=Color.black;
    private java.awt.Color fground=Color.white;
    private java.awt.Component term_area=null;
    private java.awt.Font font;

    private boolean bold=false;
    private boolean underline=false;
    private boolean reverse=false;

    private int term_width=80;
    private int term_height=24;

    private int descent=0;

    private int x=0;
    private int y=0;

    private int char_width;
    private int char_height;

    //private int line_space=0;
    private int line_space=-2;
    private int compression=0;

    private boolean antialiasing=true;

    private final Object[] colors= {Color.black, Color.red, Color.green, Color.yellow, Color.blue, Color.magenta, Color.cyan, Color.white};
    private JPopupMenu mnu;
    private Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
    protected Point selectionStart;
    protected Point selectionEnd;
    protected boolean selectionInProgress;
    JScrollPane parent;
    private JScrollBar Bar;
    
    private final BoundedRangeModel brm = new DefaultBoundedRangeModel(0,80,0,80);
    
    private ArrayList<String> StrBuffer;
    private ArrayList<Integer> clearedTimes;
    private ArrayList<Byte[]> ByteBuffer;
    private int currentLineBuffer;
    private byte[] localBuf;
    private int localoffset = 0;

    public SwingTerminal(){

        enableEvents(AWTEvent.KEY_EVENT_MASK);
        addKeyListener(this);
        setFont("Monospaced-12");

        background=new BufferedImage(char_width, char_height, BufferedImage.TYPE_INT_RGB);
        {
            Graphics2D foog=(Graphics2D)(background.getGraphics());
            foog.setColor(getBackGround());
            foog.fillRect(0, 0, char_width, char_height);
            foog.dispose();
        }

        setSize(getTermWidth(), getTermHeight());

        clear();

        term_area=this;

        setPreferredSize(new Dimension(getTermWidth(), getTermHeight()));

        setSize(getTermWidth(), getTermHeight());
        setFocusable(true);
        enableInputMethods(true);

        setFocusTraversalKeysEnabled(false);
        //  setOpaque(true);
        StrBuffer = new ArrayList<String>();
        clearedTimes = new ArrayList<Integer>();
        init();
    }
  
    public void lostOwnership(final Clipboard clipboard, final Transferable contents) {}
    
    private void init(){
        mnu = new JPopupMenu();
        mnu.setBorderPainted(true);
        mnu.setInvoker(this);
        mnu.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
        JMenuItem mnuCopy = new JMenuItem("Copia", new ImageIcon(this.getClass().getResource("/sputty/gui/resources/popupmenus/editcopy.png")));
        mnuCopy.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                mnuCopyActionListener(e);
            }
        });
        mnuCopy.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent evt){
                mnuHighlightON((JMenuItem)evt.getSource());
            }
            @Override
            public void mouseExited(MouseEvent evt){
                mnuHighlightOFF((JMenuItem)evt.getSource());
            }
        });
        mnuCopy.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
        mnu.add(mnuCopy);
        JMenuItem mnuPaste = new JMenuItem("Incolla", new ImageIcon(this.getClass().getResource("/sputty/gui/resources/popupmenus/editpaste.png")));
        mnuPaste.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                mnuPasteActionListener(e);
            }
        });
        mnuPaste.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent evt){
                mnuHighlightON((JMenuItem)evt.getSource());
            }
            @Override
            public void mouseExited(MouseEvent evt){
                mnuHighlightOFF((JMenuItem)evt.getSource());
            }
        });
        mnuPaste.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
        mnu.add(mnuPaste);
        JMenuItem mnuCopyNPaste = new JMenuItem("Copia & Incolla", new ImageIcon(this.getClass().getResource("/sputty/gui/resources/popupmenus/cpynpaste.png")));
        mnuCopyNPaste.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                mnuCopyNPasteActionListener(e);
            }
        });
        mnuCopyNPaste.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent evt){
                mnuHighlightON((JMenuItem)evt.getSource());
            }
            @Override
            public void mouseExited(MouseEvent evt){
                mnuHighlightOFF((JMenuItem)evt.getSource());
            }
        });
        mnuCopyNPaste.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
        mnu.add(mnuCopyNPaste);
        
        mnu.addSeparator();
        
        JMenuItem mnuDisconnect = new JMenuItem("Disconnetti", new ImageIcon(this.getClass().getResource("/sputty/gui/resources/popupmenus/logout.png")));
        mnuDisconnect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                mnuDisconnectActionListener(e);
            }
        });
        mnuDisconnect.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent evt){
                mnuHighlightON((JMenuItem)evt.getSource());
            }
            @Override
            public void mouseExited(MouseEvent evt){
                mnuHighlightOFF((JMenuItem)evt.getSource());
            }
        });
        mnuDisconnect.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
        mnu.add(mnuDisconnect);
        
        addMouseMotionListener(new MouseMotionAdapter() {
        
            @Override
            public void mouseDragged(final MouseEvent e) {
                final Point charCoords = new Point(e.getPoint().x / char_width , e.getPoint().y / char_height);

                if (!selectionInProgress) {
                        selectionStart = new Point(charCoords);
                        selectionInProgress = true;
                }
                repaint();
                selectionEnd = charCoords;
                selectionEnd.x = Math.min(selectionEnd.x + 1, term_width );
            }

        });
        
        
        addMouseListener(new MouseAdapter() {
            
            @Override
            public void mouseReleased(final MouseEvent e) {
                //selectionInProgress = false;
                //if ( selectionStart != null && selectionEnd != null)copySelection(selectionStart, selectionEnd);
                //repaint();
            }

            
            @Override
            public void mouseClicked(MouseEvent e) {
                MyTerminalAreaMouseClicked(e);
            }
        });
        
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                if(getHeight() == 0 && getWidth() == 0)return;
                term_height = getHeight()/char_height;
                term_width = getWidth()/char_width;
                setSize(getTermWidth(), getTermHeight());
                setPreferredSize(new Dimension(getTermWidth(), getTermHeight()));
            }
        });
        
    }

    private void setFont(String fname){
        font=java.awt.Font.decode(fname);
        BufferedImage img=new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics=(Graphics2D)(img.getGraphics());
        graphics.setFont(font);
        {
            FontMetrics fo=graphics.getFontMetrics();
            descent=fo.getDescent();
            char_width=(int)(fo.charWidth((char)'@'));
            char_height=(int)(fo.getHeight())+(line_space*2);
            descent+=line_space;
        }
        img.flush();
        graphics.dispose();
    }

    public void setSize(int w, int h){
        super.setSize(w, h);
        BufferedImage imgOrg=img;
        if(graphics!=null)graphics.dispose();

        int column=w/getCharWidth();
        int row=h/getCharHeight();
        term_width=column;
        term_height=row;

        if(emulator!=null)emulator.reset();

        img=new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        graphics=(Graphics2D)(img.getGraphics());
        graphics.setFont(font);

        clear_area(0, 0, w, h);

        if(imgOrg!=null){
            Shape clip=graphics.getClip();
            graphics.setClip(0, 0, getTermWidth(), getTermHeight());
            graphics.drawImage(imgOrg, 0, 0, term_area);
            graphics.setClip(clip);
        }

        if(cursor_graphics!=null)cursor_graphics.dispose();

        cursor_graphics=(Graphics2D)(img.getGraphics());
        cursor_graphics.setColor(getForeGround());
        cursor_graphics.setXORMode(getBackGround());

        setAntiAliasing(antialiasing);

        if(connection!=null){
            connection.requestResize(this);
        }

        if(imgOrg!=null){
            imgOrg.flush();
            imgOrg=null;
        }
    }

    public void start(Connection connection){
        this.connection=connection;
        in=connection.getInputStream();
        out=connection.getOutputStream();
        emulator=new EmulatorVT100(this, in);
        emulator.reset();
        emulator.start();
        clear();
        redraw(0, 0, getTermWidth(), getTermHeight());
    }
  
    public void run(){
        start(connection);
    }

    public void paintComponent(Graphics g){
        Graphics2D gfx = (Graphics2D)g;
        super.paintComponent(g);
        if(img!=null){
            g.drawImage(img, 0, 0, term_area);
            drawSelection(gfx);
        }
    }

    public void paint(Graphics g){
        super.paint(g);
    }

    public void processKeyEvent(KeyEvent e){
        //System.out.println(e);
        int id=e.getID();
        if(id==KeyEvent.KEY_PRESSED){
            keyPressed(e);
        }else if(id==KeyEvent.KEY_RELEASED){ 
            /*keyReleased(e);*/
        }else if(id==KeyEvent.KEY_TYPED){
            keyTyped(e);/*keyTyped(e);*/
        }
        e.consume(); // ??
    }

  byte[] obuffer=new byte[3];

    public void keyPressed(KeyEvent e){
        int keycode=e.getKeyCode();
        byte[] code=null;
        switch(keycode){
            case KeyEvent.VK_CONTROL:
            case KeyEvent.VK_SHIFT:
            case KeyEvent.VK_ALT:
            case KeyEvent.VK_CAPS_LOCK:
                return;
            case KeyEvent.VK_ENTER:
                code=emulator.getCodeENTER();
                break;
            case KeyEvent.VK_UP:
                code=emulator.getCodeUP();
                break;
            case KeyEvent.VK_DOWN:
                code=emulator.getCodeDOWN();
                break;
            case KeyEvent.VK_RIGHT:
                code=emulator.getCodeRIGHT();
                break;
            case KeyEvent.VK_LEFT:
                code=emulator.getCodeLEFT();
                break;
            case KeyEvent.VK_F1:
                code=emulator.getCodeF1();
                break;
            case KeyEvent.VK_F2:
                code=emulator.getCodeF2();
                break;
            case KeyEvent.VK_F3:
                code=emulator.getCodeF3();
                break;
            case KeyEvent.VK_F4:
                code=emulator.getCodeF4();
                break;
            case KeyEvent.VK_F5:
                code=emulator.getCodeF5();
                break;
            case KeyEvent.VK_F6:
                code=emulator.getCodeF6();
                break;
            case KeyEvent.VK_F7:
                code=emulator.getCodeF7();
                break;
            case KeyEvent.VK_F8:
                code=emulator.getCodeF8();
                break;
            case KeyEvent.VK_F9:
                code=emulator.getCodeF9();
                break;
            case KeyEvent.VK_F10:
                code=emulator.getCodeF10();
                break;
            case KeyEvent.VK_TAB:
                code=emulator.getCodeTAB();
                break;
        }
        if(code!=null){
            try{
                out.write(code, 0, code.length);
                out.flush();
            }catch(Exception ee){
            }
            return;
        }

        char keychar=e.getKeyChar();
        if((keychar&0xff00)==0){
            obuffer[0]=(byte)(e.getKeyChar());
            try{
                out.write(obuffer, 0, 1);
                out.flush();
            }catch(Exception ee){
            }
        }
     }

    public void keyTyped(KeyEvent e){
        char keychar=e.getKeyChar();
        if((keychar&0xff00)!=0){
            char[] foo=new char[1];
            foo[0]=keychar;
            try{
                byte[] goo=new String(foo).getBytes("UTF-8");
                out.write(goo, 0, goo.length);
                out.flush();
            }catch(Exception eee){
            }
        }
    }

    public int getTermWidth(){
        return char_width*term_width;
    }

    public int getTermHeight(){
        return char_height*term_height;
    }

    public int getCharWidth(){
        return char_width;
    }

    public int getCharHeight(){
        return char_height;
    }

    public int getColumnCount(){
        return term_width;
    }

    public int getRowCount(){
        return term_height;
    }

    public void clear(){
        graphics.setColor(getBackGround());
        graphics.fillRect(0, 0, char_width*term_width, char_height*term_height);
        graphics.setColor(getForeGround());
    }

    public void setCursor(int x, int y){
        //System.out.println("setCursor: "+x+","+y); 
        this.x=x;
        this.y=y;
    }

    public void draw_cursor(){
        cursor_graphics.fillRect(x, y-char_height, char_width, char_height);
        repaint(x, y-char_height, char_width, char_height);
    }

    public void redraw(int x, int y, int width, int height){
        repaint(x, y, width, height);
    }

    public void clear_area(int x1, int y1, int x2, int y2){
        //System.out.println("clear_area: "+x1+" "+y1+" "+x2+" "+y2);
        graphics.setColor(getBackGround());
        graphics.fillRect(x1, y1, x2-x1, y2-y1);
        graphics.setColor(getForeGround());
    }

    public void scroll_area(int x, int y, int w, int h, int dx, int dy){
        //System.out.println("scroll_area: "+x+" "+y+" "+w+" "+h+" "+dx+" "+dy);

        graphics.copyArea(x, y, w, h, dx, dy);
        repaint(x+dx, y+dy, w, h);
    }

    public void drawBytes(byte[] buf, int s, int len, int x, int y){
        //    clear_area(x, y, x+len*char_width, y+char_height);
        //    graphics.setColor(getForeGround());

        //graphics.drawBytes(buf, s, len, x, y-descent);
        
        if(localBuf == null){
            localBuf = new byte[len];
            localoffset = 0;
            System.arraycopy(buf, s, localBuf, localoffset, len);
        }else{
            byte[] temp = localBuf;
            localBuf = new byte[localBuf.length + len];
            System.arraycopy(temp, 0, localBuf, 0, temp.length);
            System.arraycopy(buf, s, localBuf, (localBuf.length-1)-len, len);
            localoffset = (localBuf.length-1)-len;
        }
        
        graphics.drawBytes(localBuf, localoffset, len, x, y-descent);
        System.out.println("localbuflen: " + localBuf.length + "localoffset: " + localoffset + " len: " + len + " x= " + x + " y-descent= " + (y-descent));
        /*
        String curString = new String(buf, s, len);
        StrBuffer.add(curString);
        Bar.getModel().setRangeProperties(StrBuffer.size(), 1, 0, StrBuffer.size()-1, true);
        drawString(StrBuffer.get(StrBuffer.size()-1), x, y-descent);
        currentLineBuffer = ((y+descent)+1)/char_height;
        System.out.println(currentLineBuffer);
        //System.out.println("drawBytes: "+x+","+y+" "+len+" "+ StrBuffer.get(StrBuffer.size()-1) + "CurrentLineBuffer: " + currentLineBuffer + " y-descent: " + (y-descent));
         * */
        if(bold)graphics.drawBytes(buf, s, len, x+1, y-descent);
        
        if(underline){
            graphics.drawLine(x, y-1, x+len*char_width, y-1);
        }
    }

    public void drawString(String str, int x, int y){
        //    clear_area(x, y, x+str.length()*char_width, y+char_height);
        //    graphics.setColor(getForeGround());
        //StrBuffer.add(str);
        //System.out.println("drawString: "+x+","+y+" "+ str);
        graphics.drawString(str, x, y-descent);
        /*if(currentLineBuffer == (y-descent)){
            if(str.indexOf("\n") >= 0){
                StrBuffer.add(str);
            }else{
                String str_temp = StrBuffer.get(StrBuffer.size()-1);
                str_temp = str_temp + str;
                StrBuffer.set(StrBuffer.size()-1, str_temp);
            }
        }else{*/
            //StrBuffer.add(str);
        //}
        if(bold)graphics.drawString(str, x+1, y-descent);

        if(underline){
            graphics.drawLine(x, y-1, x+str.length()*char_width, y-1);
        }
        //currentLineBuffer = y-descent;
    }

    public void beep(){
        Toolkit.getDefaultToolkit().beep();
    }

    /** Ignores key released events. */
    public void keyReleased(KeyEvent event){
    }

    public void setLineSpace(int foo){
        this.line_space=foo;
    }

    public boolean getAntiAliasing(){
        return antialiasing;
    }

    public void setAntiAliasing(boolean foo){
        if(graphics==null)return;
        antialiasing=foo;
        java.lang.Object mode=foo ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
        RenderingHints hints=new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, mode);
        graphics.setRenderingHints(hints);
    }

    public void setCompression(int compression){
        if(compression<0||9<compression)return;
        this.compression=compression;
    }

    private java.awt.Color toColor(Object o){
        if(o instanceof String){
            return java.awt.Color.getColor((String)o);
        }
        if(o instanceof java.awt.Color){
            return (java.awt.Color)o;
        }
        return Color.white;
    }

    public void setDefaultForeGround(Object f){
        defaultfground=toColor(f);
    }

    public void setDefaultBackGround(Object f){
        defaultbground=toColor(f);
    }

    public void setForeGround(Object f){
        fground=toColor(f);
        graphics.setColor(getForeGround());
    }

    public void setBackGround(Object b){
        bground=toColor(b);
        Graphics2D foog=(Graphics2D)(background.getGraphics());
        foog.setColor(getBackGround());
        foog.fillRect(0, 0, char_width, char_height);
        foog.dispose();
    }

    private java.awt.Color getForeGround(){
        if(reverse)return bground;
        return fground;
    }

    private java.awt.Color getBackGround(){
        if(reverse)return fground;
        return bground;
    }

    public Object getColor(int index){
        if(colors==null||index<0||colors.length<=index)return null;
        return colors[index];
    }

    public void setBold(){
        bold=true;
    }

    public void setUnderline(){
        underline=true;
    }

    public void setReverse(){
        reverse=true;
        if(graphics!=null)graphics.setColor(getForeGround());
    }

    public void resetAllAttributes(){
        bold=false;
        underline=false;
        reverse=false;
        bground=defaultbground;
        fground=defaultfground;
        if(graphics!=null)graphics.setColor(getForeGround());
    }
  
    public void setConnection(Connection connection){
        this.connection = connection;
    }
  
    public Connection getConnection(){
        return this.connection;
    }
  
    private void MyTerminalAreaMouseClicked(MouseEvent e){
        this.grabFocus();
        if(e.getButton() == e.BUTTON3){
            mnu.setLocation(e.getXOnScreen(), e.getYOnScreen());
            mnu.setVisible(true);
            mnu.grabFocus();
        }else{
            selectionStart = null;
            selectionEnd = null;
            selectionInProgress = false;
            repaint();
        }
    }
    
    private void mnuCopyActionListener(ActionEvent e){
        /*if(this.getSelectionStart() > 0){
            StringSelection s = new StringSelection(this.getSelectedText());
            clip.setContents(s, null);
            mnu.setVisible(false);
            this.grabFocus();
        }*/
        copySelection(selectionStart, selectionEnd);
        mnu.setVisible(false);
        this.grabFocus();
    }
    
    private void mnuPasteActionListener(ActionEvent e){
        if(clip.isDataFlavorAvailable(DataFlavor.stringFlavor)){
            try{
                Transferable T = clip.getContents(null);
                String[] data = new String[1];
                data[0] = (String)T.getTransferData(DataFlavor.stringFlavor);
                new SendCommands(in, out, data, 0,false).run();
                mnu.setVisible(false);
                this.grabFocus();
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }
    
    private void mnuCopyNPasteActionListener(ActionEvent e){
        /*if(this.getSelectionStart() > 0){
            StringSelection s = new StringSelection(this.getSelectedText());
            clip.setContents(s, null);
            try{
                Transferable T = clip.getContents(null);
                String[] data = new String[1];
                data[0] = (String)T.getTransferData(DataFlavor.stringFlavor);
                new SendCommands(in, out, data, 0,false).run();
                mnu.setVisible(false);
            }catch(Exception ex){
                ex.printStackTrace();
            }
            mnu.setVisible(false);
            this.grabFocus();
        }*/
        if(StrBuffer != null){
            if(!StrBuffer.isEmpty()){
                System.out.println("String elements: " +StrBuffer.size());
                for(int i = 0;i<StrBuffer.size();i++){
                    System.out.println(StrBuffer.get(i));
                }
            }
        }
        mnu.setVisible(false);
        this.grabFocus();
    }
    private void mnuHighlightON(JMenuItem mnuItem){
        mnuItem.setBackground(UIManager.getColor("MenuItem.selectionBackground"));  
        mnuItem.setForeground(UIManager.getColor("MenuItem.selectionForeground"));
    }
    
    private void mnuHighlightOFF(JMenuItem mnuItem){
        mnuItem.setBackground(UIManager.getColor("MenuItem.background"));   
        mnuItem.setForeground(UIManager.getColor("MenuItem.foreground"));
    }
    
    private void mnuDisconnectActionListener(ActionEvent e){
        getConnection().close();
        //((JTabbedPane)(this.getParent().getParent().getParent().getParent())).remove(((JTabbedPane)(this.getParent().getParent().getParent().getParent())).getSelectedIndex());
        ((JTabbedPane)(this.getParent().getParent())).remove(((JTabbedPane)(this.getParent().getParent())).getSelectedIndex());
        mnu.setVisible(false);
    }
    
    private void copySelection(final Point selectionStart, final Point selectionEnd) {
        if (selectionStart == null || selectionEnd == null)return;

        Point top;
        Point bottom;

        if (selectionStart.y == selectionEnd.y) {
            /* same line */
            top = selectionStart.x < selectionEnd.x ? selectionStart : selectionEnd;
            bottom = selectionStart.x >= selectionEnd.x ? selectionStart : selectionEnd;
            
            int lineBuffer = ((localBuf.length-1)/getRowCount());
            int rowBuffer = (localBuf.length-1)/getColumnCount();
            int index = 0;
            index = ((y*char_height)+(x*char_width))-((top.y * char_height) + (top.x * char_width));
            //index = (((y-descent)-top.y) * lineBuffer) + top.x;
            int sellen = (bottom.x - top.x);
            System.out.println("Lunghezza buffer: " + localBuf.length + "Index: " + index + " Sellen: " + sellen + " CurrentLineBuffer: " + currentLineBuffer);
            System.out.println(new String(localBuf, index, sellen));
        } else {
            top = selectionStart.y < selectionEnd.y ? selectionStart : selectionEnd;
            bottom = selectionStart.y > selectionEnd.y ? selectionStart : selectionEnd;
            int index = 0;
            for(int tempy = top.y;tempy <= bottom.y;tempy++){
                index = (StrBuffer.size() - currentLineBuffer) + tempy;
                System.out.println(StrBuffer.get(index));
            }
        }

        final StringBuffer selection = new StringBuffer();
        /*if( top.y < 0 ){
            final Point scrollEnd = bottom.y >= 0 ? new Point(term_width, -1) : bottom; scrollBuffer.pumpRuns(top.y, scrollEnd.y - top.y, new SelectionRunConsumer(selection, top, scrollEnd));
        }

        if( bottom.y >= 0 ){
            final Point backBegin = top.y < 0 ? new Point(0, 0) : top; backBuffer.pumpRuns( 0, backBegin.y, term_width, bottom.y -  backBegin.y + 1, new SelectionRunConsumer(selection, backBegin, bottom));
        }*/

        if(selection.length() == 0) return;
        
        try {
            clip.setContents(new StringSelection(selection.toString()), this);
        }catch(final IllegalStateException e) {
            e.printStackTrace();
        }
    }
    
    public void drawSelection(Graphics2D g) {
            /* which is the top one */
        Point top;
        Point bottom;
        g.setColor(getForeGround());
        g.setXORMode(getBackGround());
        if (selectionStart == null || selectionEnd == null)return;
        if (selectionStart.y == selectionEnd.y) {
            /* same line */
            if (selectionStart.x == selectionEnd.x)return;
            top = selectionStart.x < selectionEnd.x ? selectionStart : selectionEnd;
            bottom = selectionStart.x >= selectionEnd.x ? selectionStart : selectionEnd;
            g.fillRect(top.x * char_width, top.y * char_height, (bottom.x - top.x) * char_width, char_height);
            
        }else{
            top = selectionStart.y < selectionEnd.y ? selectionStart : selectionEnd;
            bottom = selectionStart.y > selectionEnd.y ? selectionStart : selectionEnd;
            /* to end of first line */
            g.fillRect(top.x * char_width, top.y * char_height, (term_width - top.x) * char_width, char_height);
            if (bottom.y - top.y > 1) {
                /* intermediate lines */
                g.fillRect(0, (top.y + 1) * char_height, term_width * char_width, (bottom.y - top.y - 1) * char_height);
            }
            /* from beginning of last line */
            g.fillRect(0, bottom.y * char_height, bottom.x * char_width, char_height);
        }
    }

    public void setParent(JScrollBar Bar){
        this.Bar = Bar;
        brm.setRangeProperties(0, term_height, 0 , term_height, false );
        Bar.setModel(brm);
        Bar.addAdjustmentListener(new AdjustmentListener() {
            @Override
            public void adjustmentValueChanged(AdjustmentEvent e) {
                //System.out.println(e.getValue());
            }
        });
    }
}
